﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace DDDB
{
    public struct DataPos
    {
        public UInt16 datafile;
        public UInt16 datastart;
        public bool IsEmpty
        {
            get
            {
                return datafile == 0 && datastart == 0;
            }
        }
    }
    public struct FileRange
    {
        public UInt16 start;
        public UInt16 end;
    }
    /// <summary>
    /// 位置过滤器，用来判断一个key对应的存储位置，和一定不存在的key
    /// </summary>
  
    public class PosFilter
    {
        byte[] data;
        public int Count
        {
            get
            {
                return data.Length / 4 - 1;
            }
        }
        public int MemorySize
        {
            get
            {
                return data.Length;
            }
        }
        public int UseBit
        {
            get;
            private set;
        }
        public uint BitMask
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get
            {
                return _bitmask;
            }
        }
        uint _bitmask;
        System.IO.FileStream? sync;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public uint GetIndexWithMask(uint v)
        {
            return v & _bitmask;
        }

        public PosFilter(int bit, string? syncfile = null)
        {
            if (bit < 24 || bit > 30)
                throw new Exception("use bit 24~30");
            _bitmask = 0;
            for (var i = 0; i < bit; i++)
            {
                _bitmask |= (uint)(1 << i);
            }

            UseBit = bit;
            data = new byte[((long)1 << bit) * 4 + 4];//+4是多留一个位置，用来保存新加数据的位置


            if (syncfile != null)
            {
                if (System.IO.File.Exists(syncfile) == false)
                {
                    sync = System.IO.File.Open(syncfile, FileMode.OpenOrCreate);
                    sync.Write(data, 0, data.Length);
                    sync.Position = 0;
                    SetFileRange(new FileRange { start = 0, end = 0 });
                }
                else
                {
                    sync = System.IO.File.Open(syncfile, FileMode.Open);
                    sync.Read(data, 0, data.Length);
                    sync.Position = 0;
                }
            }

        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Set(uint index, DataPos value)
        {
            unsafe
            {
                fixed (byte* dataPtr = data)
                {
                    DataPos* ptr = (DataPos*)dataPtr;
                    ptr[index] = value;
                }
                if (sync != null)
                {
                    sync.Position = index * 4;
                    sync.Write(data, (int)index * 4, 4);
                }
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public DataPos Get(uint index)
        {
            unsafe
            {
                fixed (byte* dataPtr = data)
                {
                    DataPos* ptr = (DataPos*)dataPtr;
                    return ptr[index];
                }
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public FileRange GetFileRange()
        {
            unsafe
            {
                fixed (byte* dataPtr = data)
                {
                    FileRange* ptr = (FileRange*)dataPtr;
                    return ptr[Count];
                }
            }
        }
        byte[] lastbuf = new byte[4];
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void SetFileRange(FileRange fileid)
        {
            unsafe
            {
                fixed (byte* dataPtr = data)
                {
                    FileRange* ptr = (FileRange*)dataPtr;
                    ptr[Count] = fileid;
                }

                if (sync != null)
                {
                    Array.Copy(data, (long)Count * 4, lastbuf, 0, 4);
                    sync.Position = data.LongLength - 4;
                    sync.Write(lastbuf, 0, 4);
                }
            }
        }
        public void Dispose()
        {
            if (sync != null)
            {
                sync.Close();
            }
        }
    }
}
